home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / e / amigae31apart2.lha / Amiga_E_v3.1a / Src / Utils / D.e < prev    next >
Encoding:
Text File  |  1992-09-02  |  10.4 KB  |  303 lines

  1. /* recursive directory tool
  2.  
  3. needs v37.
  4.  
  5. Universal directory lister. called with no arguments, by just typing
  6. "d", it lists the current directory. template:
  7.  
  8. DIR,REC/S,WIDTH/K/N,COL/K/N,SIZE/S,NOSORT/S,NOFILES/S,NODIRS/S,FULL/S,NOANSI/S,
  9. TARGET/K,DO/K/F
  10.  
  11. DIR        specifies an optional path to the dir you wish to list.
  12.         may contain standard wildcard patterns like #?~[]%() etc.
  13. REC        specifies that subdirectories should be listed recursively.
  14. WIDTH <num>    max width of one line of output. if not present, D will
  15.         infer this from the current width of the console.
  16.         NOTE: currently it just takes WIDTH=77 as default. does anyone
  17.         have code that gets the width from the console?
  18. COL <num>    where n=1..10, by default, D will try and fit as many
  19.         columns as allowed by WIDTH.
  20. SIZE        reports the size of each dir as it is being listed. note that
  21.         combined with REC gives sizes of whole dir (sub-)trees.
  22. NOSORT        by default, dirs are sorted before display. disable this with
  23.         the NOSORT switch.
  24. NOFILES        displays just dirs
  25. NODIRS        displays just files
  26. FULL        lists full path instead of just filename
  27. NOANSI        doesn't use ansi display codes while printing
  28. TARGET <dir>    specifies a target directory for use with DO. should
  29.         end in either "/" or ":"
  30. DO <comline>    specifies a commandline for automatic script generation.
  31.         note that this uses up the rest of D's commandline.
  32.  
  33. something should be said on the script feature: it enables you
  34. to perform repetitive tasks on whole dirs, or dir-trees. existing
  35. utilities that enabled you to do such tasks where mostly not
  36. flexible enough; d enables you to use the REC keyword in combination
  37. with scripts, allows for variable extensions: use <file>.o if
  38. the original name was <file>.s, and the spec. of a target:
  39. resulting files from the operation are placed in another dir, which
  40. can be a complete mirror image of another dir-tree. makedir
  41. statements are inserted if target: is empty.
  42.  
  43. following format codes may be used in <commandline>:
  44.  
  45. %s is file (filename+path)
  46. %f is file WITHOUT extension
  47. %r is file without extension, but with leading <dir> replaced by
  48.    <target> (usefull if <commandline> allows for an outputfile)
  49. %> or %< %>> etc. prevents the shell from thinking ">" is a redirection
  50.    for D, instead of <commandline>
  51.  
  52. a complex example:
  53. you wish to have a complete ascii reference of the emodules:
  54. directory, recursively, and with the resulting .txt files
  55. as a mirror-image directory structure somewhere else.
  56.  
  57. 1> D >ram:script emodules: REC TARGET=t:mods/ DO showmodule %>%r.txt %s
  58. 1> execute ram:script
  59.  
  60. will do that for you.
  61. for any file like "emodules:exec/io.m" D will make a line like:
  62. "showmodule  >t:mods/exec/io.txt emodules:exec/io.m"
  63.  
  64. other examples:    D >mydirlist dh0: WIDTH=100 SIZE REC NOANSI
  65.         D docs: DO type >prt: %s
  66.         D asm: TARGET=obj: DO genam %s -o%r.o
  67.         D emodules: REC TARGET=ram: DO showmodule %>%r.txt %s
  68.  
  69. */
  70.  
  71. OPT OSVERSION=37
  72.  
  73. CONST MAXPATH=250
  74.  
  75. ENUM ER_NONE,ER_BADARGS,ER_MEM,ER_UTIL,ER_ITARG,ER_COML
  76. ENUM ARG_DIR,ARG_REC,ARG_WIDTH,ARG_COL,ARG_SIZE,ARG_NOSORT,ARG_NOFILES,
  77.      ARG_NODIRS,ARG_FULL,ARG_NOANSI,ARG_TARGET,ARG_COMMAND,NUMARGS
  78.  
  79. MODULE 'dos/dosasl', 'dos/dos', 'utility'
  80.  
  81. RAISE ER_MEM IF New()=NIL,      /* set common exceptions:                */
  82.       ER_MEM IF String()=NIL,      /* every call to these functions will be */
  83.       ERROR_BREAK IF CtrlC()=TRUE /* automatically checked against NIL,    */
  84.                   /* and the exception ER_MEM is raised    */
  85.  
  86. DEF dir,command,target,
  87.     recf=FALSE,col=3,calccolf=TRUE,comf=FALSE,sizef=FALSE,sortf=TRUE,filesf=TRUE,
  88.     fullf=FALSE,ansif=TRUE,dirsf=TRUE,dirw[100]:STRING,
  89.     rdargs=NIL,work[250]:STRING,work2[250]:STRING,dirno=0,
  90.     prtab[25]:LIST,prcopy[25]:LIST,workdir[250]:STRING,
  91.     consolewidth=0
  92.  
  93. PROC main() HANDLE
  94.   DEF args[NUMARGS]:LIST,templ,x,lock,fib:fileinfoblock,s
  95.   IF (utilitybase:=OpenLibrary('utility.library',37))=NIL THEN Raise(ER_UTIL)
  96.   FOR x:=0 TO NUMARGS-1 DO args[x]:=0
  97.   templ:='DIR,REC/S,WIDTH/K/N,COL/K/N,SIZE/S,NOSORT/S,NOFILES/S,NODIRS/S,' +
  98.          'FULL/S,NOANSI/S,TARGET/K,DO/K/F'
  99.   rdargs:=ReadArgs(templ,args,NIL)
  100.   IF rdargs=NIL THEN Raise(ER_BADARGS)        /* initialise flags */
  101.   IF args[ARG_SIZE] THEN sizef:=TRUE        /* from command line args */
  102.   consolewidth:=Bounds(IF args[ARG_WIDTH] THEN Long(args[ARG_WIDTH]) ELSE findconsolewidth(),1,1000)
  103.   IF args[ARG_COL] THEN (calccolf:=FALSE) BUT col:=Long(args[ARG_COL])
  104.   col:=Bounds(col,1,100)
  105.   IF args[ARG_NOSORT] THEN sortf:=FALSE
  106.   IF args[ARG_NOANSI] THEN ansif:=FALSE
  107.   IF args[ARG_NOFILES] THEN filesf:=FALSE
  108.   IF args[ARG_NODIRS] THEN dirsf:=FALSE
  109.   IF args[ARG_REC] THEN recf:=TRUE
  110.   IF args[ARG_FULL] THEN fullf:=TRUE
  111.   target:=args[ARG_TARGET]
  112.   command:=args[ARG_COMMAND]
  113.   IF command THEN comf:=TRUE
  114.   IF target
  115.     x:=target+StrLen(target)-1
  116.     IF (x<target) OR ((x[]<>":") AND (x[]<>"/")) THEN Raise(ER_ITARG)
  117.   ENDIF
  118.   IF comf
  119.     sortf:=FALSE    /* read and convert commandline for scripts */
  120.     col:=1
  121.     filesf:=FALSE
  122.     dirsf:=FALSE
  123.     IF command[]=0 THEN Raise(ER_COML)
  124.     s:=command
  125.     WHILE x:=s[]++
  126.       IF x="%"
  127.         x:=s[]
  128.         SELECT x
  129.           CASE "s"; ListAdd(prtab,[1],1)            /* %s = fullpath */
  130.           CASE "f"; ListAdd(prtab,NEW [work],1); s[]:="s"    /* %f = work     */
  131.           CASE "r"; ListAdd(prtab,NEW [work2],1); s[]:="s"    /* %r = work2    */
  132.           DEFAULT; s[-1]:=" "
  133.         ENDSELECT
  134.       ENDIF
  135.     ENDWHILE
  136.   ENDIF
  137.   dir:=args[ARG_DIR]
  138.   IF dir THEN StrCopy(dirw,dir,ALL)
  139.   lock:=Lock(dirw,-2)
  140.   IF lock                  /* if yes, the prob. dir, else wildcard */
  141.     IF Examine(lock,fib) AND (fib.direntrytype>0)
  142.       AddPart(dirw,'#?',100)
  143.     ENDIF
  144.     UnLock(lock)
  145.   ENDIF
  146.   recdir(dirw)
  147.   Raise(ER_NONE)
  148. EXCEPT
  149.   IF rdargs THEN FreeArgs(rdargs)
  150.   IF utilitybase THEN CloseLibrary(utilitybase)
  151.   SELECT exception
  152.     CASE ER_BADARGS;            PrintF('Bad Arguments for D!\n')
  153.     CASE ER_MEM;                PrintF('No mem!\n')
  154.     CASE ER_COML;               PrintF('No commandline specified\n')
  155.     CASE ER_ITARG;              PrintF('Illegal target\n')
  156.     CASE ER_UTIL;               PrintF('Could not open "utility.library" v37\n')
  157.     CASE ERROR_BREAK;           PrintF('User terminated D\n')
  158.     CASE ERROR_BUFFER_OVERFLOW; PrintF('Internal error\n')
  159.     DEFAULT;                    PrintFault(exception,'Dos Error')
  160.   ENDSELECT
  161. ENDPROC
  162.  
  163. PROC recdir(dirr) HANDLE
  164.   DEF er,i:PTR TO fileinfoblock,size=0,anchor=NIL:PTR TO anchorpath,fullpath,
  165.       flist=NIL,first,entries=0,ascii,w,x,y,z,flist2=NIL,
  166.       isfirst=0,maxfilename=1,maxfilesize=-1,lcol
  167.   anchor:=New(SIZEOF anchorpath+MAXPATH)
  168.   anchor.breakbits:=4096
  169.   anchor.strlen:=MAXPATH-1
  170.   er:=MatchFirst(dirr,anchor)            /* collect all strings */
  171.   WHILE er=0
  172.     fullpath:=anchor+SIZEOF anchorpath
  173.     i:=anchor.info
  174.     ascii:=IF fullf THEN fullpath ELSE i.filename
  175.     IF i.direntrytype>0 
  176.       StringF(work,'\s\l\s[30]         ',IF ansif THEN '\e' ELSE '',ascii)
  177.     ELSE
  178.       StringF(work,'\l\s[30] \r\d[8]',ascii,i.size)
  179.       IF i.size>maxfilesize THEN maxfilesize:=i.size
  180.     ENDIF
  181.     x:=StrLen(ascii)
  182.     IF x>maxfilename THEN maxfilename:=x
  183.     IF IF i.direntrytype>0 THEN dirsf ELSE filesf
  184.       first:=String(EstrLen(work))
  185.       StrCopy(first,work,ALL)
  186.       flist:=Link(first,flist)
  187.       INC entries
  188.     ENDIF
  189.     IF i.direntrytype<0 THEN size:=size+i.size
  190.     IF (i.direntrytype<0) AND comf        /* execute commandline */
  191.       ListCopy(prcopy,prtab,ALL)
  192.       IF comf THEN MapList({x},prcopy,prcopy,`IF x=1 THEN fullpath ELSE x)
  193.       StrCopy(work,fullpath,ALL)
  194.       x:=InStr(work,'.',0)
  195.       IF x<>-1 THEN SetStr(work,x)        /* find f% */
  196.       IF target
  197.         StrCopy(work2,target,ALL)
  198.         x:=work; y:=dirw        /* was dirr */
  199.         WHILE x[]++=y[]++ DO NOP
  200.         DEC x
  201.         StrAdd(work2,x,ALL)            /* find r% */
  202.       ELSE
  203.         StrCopy(work2,work,ALL)
  204.       ENDIF
  205.       IF isfirst++=0
  206.         StrCopy(workdir,work2,ALL)        /* see if makedir is needed */
  207.         SetStr(workdir,PathPart(work2)-work2)
  208.         x:=Lock(workdir,-2)
  209.         IF x THEN UnLock(x) ELSE PrintF('makedir \s\n',workdir)
  210.       ENDIF
  211.       Flush(stdout); VfPrintf(stdout,command,prcopy); Flush(stdout)
  212.       PrintF('\n')
  213.     ENDIF
  214.     IF recf AND (i.direntrytype>0)        /* do recursion(=tail) */
  215.       x:=StrLen(fullpath)
  216.       IF x+5<MAXPATH THEN CopyMem('/#?',fullpath+x,4)
  217.       size:=size+recdir(fullpath)
  218.       fullpath[x]:=0
  219.     ENDIF
  220.     er:=MatchNext(anchor)
  221.   ENDWHILE
  222.   IF er<>ERROR_NO_MORE_ENTRIES THEN Raise(er)
  223.   MatchEnd(anchor)
  224.   Dispose(anchor)
  225.   anchor:=NIL
  226.   maxfilesize:=IF maxfilesize>=0 THEN sillylog10(maxfilesize) ELSE 0
  227.   lcol:=Bounds(IF calccolf THEN consolewidth+1/(maxfilesize+maxfilename+2) ELSE col,1,100)
  228.   flist:=Link(String(1),flist)
  229.   IF entries>2 AND sortf THEN flist:=sort(flist)
  230.   IF comf=FALSE                        /* display dir */
  231.     IF dirno THEN PrintF('\n')
  232.     PrintF(IF ansif THEN '\e[1mDirectory of: "\s"\e[0m\n' ELSE 'Directory of: "\s"\n',dirr)
  233.   ENDIF
  234.   first:=flist
  235.   x:=entries/lcol          /* put dirlist in columns */
  236.   IF x*lcol<entries THEN INC x
  237.   FOR z:=1 TO x
  238.     first:=Next(first)
  239.     flist2:=first
  240.     FOR y:=1 TO lcol
  241.       IF flist2
  242.         w:=maxfilename
  243.         IF flist2[]="\e"
  244.           flist2[w+1]:=0
  245.           IF ansif THEN PutStr('\e[1;32m')
  246.           PrintF('\s \s',flist2+1,flist2+40-maxfilesize)
  247.           IF ansif THEN PutStr('\e[0;31m')
  248.         ELSE
  249.           flist2[w]:=0
  250.           PrintF('\s \s',flist2,flist2+39-maxfilesize)
  251.         ENDIF
  252.         flist2:=Forward(flist2,x)
  253.         IF y<>lcol THEN PrintF(' ')
  254.       ENDIF
  255.     ENDFOR
  256.     PrintF('\n')
  257.     CtrlC()
  258.   ENDFOR
  259.   IF sizef THEN PrintF('BYTE SIZE: \d\n',size)
  260.   DisposeLink(flist)
  261.   INC dirno
  262. EXCEPT                                  /* nested exception handlers! */
  263.   IF anchor THEN MatchEnd(anchor)
  264.   Raise(exception)  /* this way, we call _all_ handlers in the recursion  */
  265. ENDPROC size        /* and thus calling MatchEnd() on all hanging anchors */
  266.  
  267. PROC sort(flist)
  268.   DEF sortdone,prev,first,next,nnext
  269.   REPEAT
  270.     sortdone:=TRUE                /* sort dirlist */
  271.     prev:=first:=flist
  272.     WHILE first:=Next(first)
  273.       IF next:=Next(first)
  274.         IF Stricmp(first,next)>0
  275.           nnext:=Next(next)
  276.           Link(prev,first:=Link(next,Link(first,nnext)))
  277.           sortdone:=FALSE
  278.         ENDIF
  279.       ENDIF
  280.       prev:=first
  281.     ENDWHILE
  282.     CtrlC()
  283.   UNTIL sortdone
  284. ENDPROC flist
  285.  
  286. PROC findconsolewidth()
  287.   /*
  288.   DEF buf[20]:ARRAY
  289.   Write(stdout,[$9B,"0"," ","q"]:CHAR,4)
  290.   IF WaitForChar(stdin,100000)
  291.     Read(stdin,buf,5)
  292.     IF StrCmp(buf,[$9B313B31]:LONG,4)
  293.       WriteF('yes\n')
  294.     ELSE
  295.       WriteF('no\n')
  296.     ENDIF
  297.   ENDIF
  298.   WriteF('um\n')
  299.   */
  300. ENDPROC 77 ->99
  301.  
  302. PROC sillylog10(n) IS IF n<10 THEN 1 ELSE sillylog10(Div(n,10))+1
  303.